package contentManage

import (
	"bufio"
	"errors"
	"fmt"
	"github.com/gin-gonic/gin"
	"log"
	"main/src/apps"
	"main/src/utils"
	"mime/multipart"
	"strconv"
	"time"
)

type CreateContentDto struct {
	Article string `json:"article" binding:"required,min=1"` // 文章内容
	Cat     int    `json:"cat"`
}

func (dto *CreateContentDto) CreateContent(c *gin.Context) (res ContentInfoResponseDto, err error) {
	model := &Content{
		Article: dto.Article,
		Cat:     dto.Cat,
	}
	result := apps.DB.Create(model)
	err = result.Error
	if err != nil {
		utils.Response(
			c,
			"插入失败err: "+err.Error(),
			utils.Status.Error,
			nil,
		)
	} else {
		res.format(*model)
	}
	return res, err
}

type GetContentDto struct {
	utils.GetDataLimitDto
}

type KeywordInfoResponseDto struct {
	Id        int       `json:"id"`
	Text      string    `json:"text"`
	Cat       int       `json:"cat"`
	CreatedAt time.Time `json:"created_at"`
	UpdatedAt time.Time `json:"updated_at"`
}

func (dto *KeywordInfoResponseDto) format(keyword KeyWord) {
	dto.Text = keyword.Text
	dto.Id = keyword.Id
	dto.Cat = keyword.Cat
	dto.CreatedAt = keyword.CreatedAt
	dto.UpdatedAt = keyword.UpdatedAt
}

type ImageInfoResponseDto struct {
	Id        int       `json:"id"`
	URL       string    `json:"url"`
	Cat       int       `json:"cat"`
	CreatedAt time.Time `json:"created_at"`
	UpdatedAt time.Time `json:"updated_at"`
}

func (dto *ImageInfoResponseDto) format(image Image) {
	dto.URL = image.URL
	dto.Id = image.Id
	dto.Cat = image.Cat
	dto.CreatedAt = image.CreatedAt
	dto.UpdatedAt = image.UpdatedAt
}

type ContentInfoResponseDto struct {
	Id        int       `json:"id"`
	Article   string    `json:"article"` // 文章内容
	Cat       int       `json:"cat"`
	CreatedAt time.Time `json:"created_at"`
	UpdatedAt time.Time `json:"updated_at"`
}

func (dto *ContentInfoResponseDto) format(content Content) {
	dto.Id = content.Id
	dto.Article = content.Article
	dto.Cat = content.Cat
	dto.CreatedAt = content.CreatedAt
	dto.UpdatedAt = content.UpdatedAt
}

func (dto *GetContentDto) Get(c *gin.Context) (responseDto utils.GetDataLimitResponseDto, err error) {
	dto.Init()
	if dto.PageNum < 0 {
		utils.Response(c, "page_num < 0", utils.Status.Error, nil)
		return responseDto, errors.New("page < 0")
	}
	var contents []*ContentInfoResponseDto
	var models []Content
	var count int64
	apps.DB.Model(&Content{}).Count(&count).Limit(dto.PageSize).Offset((dto.PageNum - 1) * dto.PageSize).Find(&models)

	for i := range models {
		temp := &ContentInfoResponseDto{}
		temp.format(models[i])
		contents = append(contents, temp)
	}
	responseDto.Init(dto.GetDataLimitDto, count, contents)
	return responseDto, err
}

type UpdateContentDto struct {
	Id      int    `json:"id" binding:"required"`
	Cat     string `json:"cat"`
	Article string `json:"article"` // 文章内容
}

func (dto *UpdateContentDto) UpdateContent(c *gin.Context) (ctn *Content, err error) {
	content := &Content{Id: dto.Id}
	result := apps.DB.Where(content).Find(&content)
	if result.Error == nil && len(content.Article) > 0 {
		if dto.Article != "" {
			content.Article = dto.Article
		}
		if dto.Cat != "" {
			content.Cat, err = strconv.Atoi(dto.Cat)
			if err != nil {
				utils.Response(
					c,
					"更新失败: int cat = "+dto.Cat,
					utils.Status.Error,
					nil,
				)

				return nil, err
			}
		}
		result = apps.DB.Save(&content)
		err = result.Error
	}
	if err == nil && result.RowsAffected == 0 {
		err = errors.New("该数据以删除，或没有该ID")
	}
	if err != nil {
		utils.Response(
			c,
			"更新失败err: "+err.Error(),
			utils.Status.Error,
			nil,
		)
	}
	return content, err
}

type DeleteContentDto struct {
	Id int `json:"id" binding:"required"`
}

func (dto *DeleteContentDto) DeleteContent(c *gin.Context) (err error) {
	result := apps.DB.Delete(&Content{Id: dto.Id})
	err = result.Error
	if err != nil {
		utils.Response(
			c,
			"删除失败err: "+err.Error(),
			utils.Status.Error,
			nil,
		)
	}
	return err
}

// ImageManager

type GetImageDto struct {
	utils.GetDataLimitDto
	Cat string `json:"cat"`
}

func (dto *GetImageDto) Get(c *gin.Context) (responseDto utils.GetDataLimitResponseDto, err error) {
	dto.Init()
	if dto.PageNum < 0 {
		utils.Response(c, "page_num < 0", utils.Status.Error, nil)
		return responseDto, errors.New("page < 0")
	}
	var images []*ImageInfoResponseDto
	var models []Image
	var count int64
	if dto.Cat == "" {
		apps.DB.Model(&Image{}).Count(&count).Limit(dto.PageSize).Offset((dto.PageNum - 1) * dto.PageSize).Find(&models)
	} else {
		apps.DB.Model(&Image{}).Where("cat == '" + dto.Cat + "' ").Count(&count).Limit(dto.PageSize).Offset((dto.PageNum - 1) * dto.PageSize).Find(&models)
	}
	for i := range models {
		temp := &ImageInfoResponseDto{}
		temp.format(models[i])
		images = append(images, temp)
	}
	responseDto.Init(dto.GetDataLimitDto, count, images)
	return responseDto, err
}

type CreateImageDto struct {
	URL string `json:"url" binding:"required,min=1"` // 轮链
	Cat int    `json:"cat"`
}

func (dto *CreateImageDto) Create(c *gin.Context) (image ImageInfoResponseDto, err error) {
	model := &Image{
		URL: dto.URL,
		Cat: dto.Cat,
	}
	result := apps.DB.Create(model)
	err = result.Error
	if err != nil {
		utils.Response(
			c,
			"插入失败err: "+err.Error(),
			utils.Status.Error,
			nil,
		)
	} else {
		image.format(*model)
	}
	return image, err
}

type UpdateImageDto struct {
	Id  int    `json:"id"`
	URL string `json:"url"` // 轮链
	Cat string `json:"cat"`
}

func (dto *UpdateImageDto) UpdateImage(c *gin.Context) (img *Image, err error) {
	l := &Image{Id: dto.Id}
	result := apps.DB.Where(l).Find(&l)
	if result.Error == nil && len(l.URL) > 0 {
		if dto.URL != "" {
			l.URL = dto.URL
		}
		if dto.Cat != "" {
			l.Cat, err = strconv.Atoi(dto.Cat)
		}
		if err != nil {
			utils.Response(
				c,
				"更新失败: int cat = "+dto.Cat,
				utils.Status.Error,
				nil,
			)

			return nil, err
		}
		result = apps.DB.Save(&l)
		err = result.Error
	}
	if err == nil && result.RowsAffected == 0 {
		err = errors.New("该数据以删除，或没有该ID")
	}
	if err != nil {
		utils.Response(
			c,
			"更新失败err: "+err.Error(),
			utils.Status.Error,
			nil,
		)
	}
	return l, err
}

type DeleteImageDto struct {
	Id int `json:"id"`
}

func (dto *DeleteImageDto) DeleteImage(c *gin.Context) (err error) {
	result := apps.DB.Delete(&Image{Id: dto.Id})
	err = result.Error
	if err != nil {
		utils.Response(
			c,
			"删除失败err: "+err.Error(),
			utils.Status.Error,
			nil,
		)
	}
	return err
}

// KeyWordManager

type GetKeyWordDto struct {
	utils.GetDataLimitDto
	Text string `json:"text"`
	Cat  string `json:"cat"`
}

func (dto *GetKeyWordDto) Get(c *gin.Context) (responseDto utils.GetDataLimitResponseDto, err error) {
	dto.Init()
	if dto.PageNum < 0 {
		utils.Response(c, "page_num < 0", utils.Status.Error, nil)
		return responseDto, errors.New("page < 0")
	}
	var keywords []*KeywordInfoResponseDto
	var models []KeyWord
	var count int64
	if dto.Text != "" && dto.Cat != "" {
		apps.DB.Where("`text` like '%" + dto.Text + "%' and cat = '" + dto.Cat + "' ").Model(&KeyWord{}).Count(&count).Limit(dto.PageSize).Offset((dto.PageNum - 1) * dto.PageSize).Find(&models)
	} else if dto.Text != "" {
		apps.DB.Where("`text` like '%" + dto.Text + "%' ").Model(&KeyWord{}).Count(&count).Limit(dto.PageSize).Offset((dto.PageNum - 1) * dto.PageSize).Find(&models)
	} else if dto.Cat != "" {
		apps.DB.Where("cat = '" + dto.Cat + "' ").Model(&KeyWord{}).Count(&count).Limit(dto.PageSize).Offset((dto.PageNum - 1) * dto.PageSize).Find(&models)
	} else {
		apps.DB.Model(&KeyWord{}).Count(&count).Limit(dto.PageSize).Offset((dto.PageNum - 1) * dto.PageSize).Find(&models)
	}

	for i := range models {
		temp := &KeywordInfoResponseDto{}
		temp.format(models[i])
		keywords = append(keywords, temp)
	}
	responseDto.Init(dto.GetDataLimitDto, count, keywords)
	return responseDto, err
}

type CreateKeyWordDto struct {
	Text string `json:"text" binding:"required,min=1"` // 轮链
	Cat  int    `json:"cat"`
}

func (dto *CreateKeyWordDto) Create(c *gin.Context) (keyword KeywordInfoResponseDto, err error) {
	model := &KeyWord{
		Text: dto.Text,
		Cat:  dto.Cat,
	}
	result := apps.DB.Create(model)
	log.Println(model)
	err = result.Error
	if err != nil {
		utils.Response(
			c,
			"插入失败err: "+err.Error(),
			utils.Status.Error,
			nil,
		)
	} else {
		keyword.format(*model)
	}
	return keyword, err
}

type UpdateKeyWordDto struct {
	Id   int    `json:"id"`
	Text string `json:"text"` // 轮链
	Cat  string `json:"cat"`
}

func (dto *UpdateKeyWordDto) UpdateKeyword(c *gin.Context) (keyword *KeyWord, err error) {
	k := &KeyWord{Id: dto.Id}
	result := apps.DB.Where(k).Find(&k)
	if result.Error == nil && len(k.Text) > 0 {
		if dto.Text != "" {
			k.Text = dto.Text
		}
		if dto.Cat != "" {
			k.Cat, err = strconv.Atoi(dto.Cat)
		}
		if err != nil {
			utils.Response(
				c,
				"更新失败: int cat = "+dto.Cat,
				utils.Status.Error,
				nil,
			)

			return nil, err
		}
		result = apps.DB.Save(&k)
		err = result.Error
	}
	if err == nil && result.RowsAffected == 0 {
		err = errors.New("该数据以删除，或没有该ID")
	}
	if err != nil {
		utils.Response(
			c,
			"更新失败err: "+err.Error(),
			utils.Status.Error,
			nil,
		)
	}
	return k, err
}

type DeleteKeywordDto struct {
	Id int `json:"id"`
}

func (dto *DeleteKeywordDto) DeleteKeyword(c *gin.Context) (err error) {
	result := apps.DB.Delete(&KeyWord{Id: dto.Id})
	err = result.Error
	if err != nil {
		utils.Response(
			c,
			"删除失败err: "+err.Error(),
			utils.Status.Error,
			nil,
		)
	}
	return err
}

type ExportFileByKeyword struct {
	File *multipart.FileHeader
	Cat  int `form:"cat"`
}

type ExportFileByImage struct {
	File *multipart.FileHeader
	Cat  int `form:"cat"`
}

func (e *ExportFileByKeyword) Export(c *gin.Context) (ctn []KeywordInfoResponseDto, err error) {
	// 打开文件
	f, err := e.File.Open()
	if err != nil {
		utils.Response(c, fmt.Sprintf("打开文件失败：%s", err.Error()), utils.Status.Error, nil)
		return
	}
	defer f.Close()
	ctn = []KeywordInfoResponseDto{}
	// 逐行读取文本内容
	scanner := bufio.NewScanner(f)
	for scanner.Scan() {
		line := scanner.Text()
		keyword := KeyWord{
			Text: line,
			Cat:  e.Cat,
		}
		apps.DB.Create(&keyword)
		log.Println(line)
	}
	return ctn, err
}

func (e *ExportFileByImage) Export(c *gin.Context) (ctn []ImageInfoResponseDto, err error) {
	// 打开文件
	f, err := e.File.Open()
	if err != nil {
		utils.Response(c, fmt.Sprintf("打开文件失败：%s", err.Error()), utils.Status.Error, nil)
		return
	}
	defer f.Close()
	ctn = []ImageInfoResponseDto{}
	// 逐行读取文本内容
	scanner := bufio.NewScanner(f)
	for scanner.Scan() {
		line := scanner.Text()
		image := Image{
			URL: line,
			Cat: e.Cat,
		}
		apps.DB.Create(&image)
		log.Println(line)
	}
	return ctn, err
}
